package com.noah2021.service.impl;

import com.noah2021.dao.ItemStockDOMapper;
import com.noah2021.dao.PromoDOMapper;
import com.noah2021.pojo.ItemStockDO;
import com.noah2021.pojo.ItemStockDOExample;
import com.noah2021.pojo.PromoDO;
import com.noah2021.service.ItemService;
import com.noah2021.service.UserService;
import com.noah2021.service.model.ItemModel;
import com.noah2021.service.model.PromoModel;
import com.noah2021.service.PromoService;
import com.noah2021.service.model.UserModel;
import com.noah2021.util.Common;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * 〈〉
 *
 * @author Noah2021
 * @create 2021/2/9
 * @return
 */
@Service
@Slf4j
public class PromoServiceImpl implements PromoService {

    @Autowired
    PromoDOMapper promoDOMapper;

    @Autowired
    private ItemService itemService;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserService userService;
    @Override
    public PromoModel getPromoByItemId(Integer itemId) {
        PromoDO promoDO = promoDOMapper.selectByItemId(itemId);
        PromoModel promoModel = convertFromPojo(promoDO);
        if (promoModel == null)
            return null;
//        开始时间是现在的后面  还没开始 还不知道
        if (promoModel.getStartDate().isAfterNow())
//            promoModel.setStatus(1);
            promoModel.setStatus(Common.StockLogStatus.UNKNOW);
        else if (promoModel.getEndDate().isBeforeNow())
//            promoModel.setStatus(3);
//            结束时间比现在早 已经结束了
            promoModel.setStatus(Common.StockLogStatus.ROLLBACK_MESSAGE);
        else
//            promoModel.setStatus(2);
            promoModel.setStatus(Common.StockLogStatus.COMMIT_MESSAGE);
        return promoModel;
    }

    @Override
    public int save(PromoDO promoDO) {
        Integer id = promoDO.getId();
        PromoDO promoDOFromDb = promoDOMapper.selectByPrimaryKey(id);
        if (promoDOFromDb==null) {
            int insert = promoDOMapper.insert(promoDO);
            return insert;
        }
        int updateRes = promoDOMapper.updateByPrimaryKey(promoDO);
        return updateRes;
    }

    @Autowired
    ItemStockDOMapper itemStockDOMapper;
    /**
     * 在这里初始化了商品的库存 存在 redis里面
     * item id 怎么知道呢 活动发布的时候 直接改数据库吗
     * 创建活动的时候 如果已经有这个商品的活动 就不创建
     * @param promoId
     */
    @Override
    public void publishPromo(Integer promoId) {
//        这里的stock 是错的 啊
        PromoDO promoDO = promoDOMapper.selectByPrimaryKey(promoId);
//        itemStockDOMapper.s
        Integer itemId = promoDO.getItemId();
//        mybatis  example

        if(promoDO==null){
            return;
        }


        if (promoDO.getItemId() == null || promoDO.getItemId().intValue() == 0)
            return;

        ItemStockDOExample itemStockDOExample=new ItemStockDOExample() ;
        itemStockDOExample.createCriteria().andItemIdEqualTo(itemId);
        List<ItemStockDO> itemStockDOS = itemStockDOMapper.selectByExample(itemStockDOExample);
//        itemStockDOMapper
        if (itemStockDOS==null) {
//            没有
            log.info("没有这个item id的 ");
            return;
        }
        ItemStockDO itemStockDO = itemStockDOS.get(0);
        Integer stock = itemStockDO.getStock();
//        itemModel.getStock();

        ItemModel itemModel = itemService.getItemById(promoDO.getItemId());
//        itemModel.getStock();
        redisTemplate.opsForValue().set("promo_item_stock_" + itemModel.getId(),
                stock);
        //将大闸限制的数字设到redis内
        redisTemplate.opsForValue().set("promo_door_count_"+promoId,
                stock*5);

//        redisTemplate.opsForValue().set("promo_item_stock_" + itemModel.getId(),
//                itemModel.getStock());
//        //将大闸限制的数字设到redis内
//        redisTemplate.opsForValue().set("promo_door_count_"+promoId,
//                itemModel.getStock().intValue()*5);
    }

    /**
     * 需要redis 生成令牌失败 可能redis 没有开启
     * @param promoId
     * @param itemId
     * @param userId
     * @return
     */
    @Override
    public String generateSecondKillToken(Integer promoId,Integer itemId,Integer userId) {

        //判断是否库存已售罄，若对应的售罄key存在，则直接返回下单失败
        if(redisTemplate.hasKey("promo_item_stock_invalid_"+itemId)){
            log.info("已经售罄");
            return null;
        }
//        promoId null
        PromoDO promoDO = promoDOMapper.selectByPrimaryKey(promoId);
        log.info("promoDO {}",promoDO);

        //dataobject->model
        PromoModel promoModel = convertFromPojo(promoDO);
        if(promoModel == null){
            log.info("没有促销实体");
            return null;
        }

        //判断当前时间是否秒杀活动即将开始或正在进行
        if(promoModel.getStartDate().isAfterNow()){
            promoModel.setStatus(1);
        }else if(promoModel.getEndDate().isBeforeNow()){
            promoModel.setStatus(3);
        }else{
            promoModel.setStatus(2);
        }
        //判断活动是否正在进行
        if(promoModel.getStatus().intValue() != 2){
            log.info("活动没有在进行");
            return null;
        }
        //判断item信息是否存在
        ItemModel itemModel = itemService.getItemByIdInCache(itemId);
        if(itemModel == null){
            log.info("item信息不存在");
            return null;
        }
        //判断用户信息是否存在
        UserModel userModel = userService.getUserByIdInCache(userId);
        if(userModel == null){
            log.info("用户信息不存在");
            return null;
        }

        //获取秒杀大闸的count数量
//        -3 result
        long result = redisTemplate.opsForValue().increment(
                "promo_door_count_"+promoId,-1);
        if(result < 0){
            log.info("秒杀大闸的count数量 小于0  数量是 {}",result);
            return null;
        }
        //生成token并且存入redis内并给一个5分钟的有效期
        String token = UUID.randomUUID().toString().replace("-","");

        redisTemplate.opsForValue().set("promo_token_"+promoId+"_userid_"+userId+"_itemid_"+itemId,token);
        redisTemplate.expire("promo_token_"+promoId+"_userid_"+userId+"_itemid_"+itemId,5, TimeUnit.MINUTES);

        return token;
    }

    public PromoModel convertFromPojo(PromoDO promoDO) {
        if (promoDO == null) {
            return null;
        }
        PromoModel promoModel = new PromoModel();
        BeanUtils.copyProperties(promoDO, promoModel);
        promoModel.setPromoItemPrice(new BigDecimal(promoDO.getPromoItemPrice()));
        promoModel.setStartDate(new DateTime(promoDO.getStartDate()));
        promoModel.setEndDate(new DateTime(promoDO.getEndDate()));
        return promoModel;
    }
}
